home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / cpp114.zoo / src / comment.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-20  |  5.5 KB  |  238 lines

  1.  
  2. /*---------------------------------------------------------------------*\
  3. |                                    |
  4. | CPP -- a stand-alone C preprocessor                    |
  5. | Copyright (c) 1993-95 Hacker Ltd.        Author: Scott Bigham    |
  6. |                                    |
  7. | Permission is granted to anyone to use this software for any purpose    |
  8. | on any computer system, and to redistribute it freely, with the    |
  9. | following restrictions:                        |
  10. | - No charge may be made other than reasonable charges for repro-    |
  11. |     duction.                                |
  12. | - Modified versions must be clearly marked as such.            |
  13. | - The author is not responsible for any harmful consequences of    |
  14. |     using this software, even if they result from defects therein.    |
  15. |                                    |
  16. | comment.c -- comment and whitespace processing            |
  17. \*---------------------------------------------------------------------*/
  18.  
  19. #include <stddef.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include <stdlib.h>
  23. #include "global.h"
  24.  
  25. #define SPC_GRAN 16
  26. #define LINEBUF 128
  27.  
  28. char *the_comment;
  29. size_t len_comment;
  30. static char *spc_buf = 0;
  31. static size_t sz_spc_buf;
  32.  
  33. static char SC_nested[] = "nested comment (began at line %lu)",
  34.         SC_unterm[] = "unterminated comment (began at line %ld)";
  35.  
  36. #if 0        /* not used anymore */
  37. /*
  38.    find_start_comment() -- return a pointer to the first comment-start
  39.    sequence after |s|, or |NULL| if none is found
  40. */
  41. static char *find_start_comment(s)
  42.   register char *s;
  43. {
  44.   register int in_dq = 0, in_sq = 0;
  45.  
  46.   for (;;) {
  47.     switch (*s++) {
  48.     case '\0':
  49.       return NULL;
  50.     case '\\':
  51.       s++;
  52.       continue;
  53.     case '"':
  54.       if (!in_sq)
  55.     in_dq ^= 1;
  56.       break;
  57.     case '\'':
  58.       if (!in_dq)
  59.     in_sq ^= 1;
  60.       break;
  61.     case '/':
  62.       if (!in_dq && !in_sq && *s == '*')
  63.     return s - 1;
  64.     }
  65.   }
  66. }
  67. #endif /* 0 */
  68.  
  69. /*
  70.    find_end_comment() -- return a pointer to the first character after the
  71.    current comment, or end of line if the comment does not end on this line.
  72. */
  73. static char *find_end_comment(s)
  74.   register char *s;
  75. {
  76.   for (; *s; s++) {
  77.     if (*s == '*' && s[1] == '/')
  78.       return s + 2;
  79.   }
  80.   return NULL;
  81. }
  82.  
  83. /*
  84.    nest_check() -- examine the body of a comment for comment-start sequences.
  85.    Return 1 if one is found, 0 if not.
  86. */
  87. static int nest_check(s, t)
  88.   register char *s, *t;
  89. {
  90.   register char *u;
  91.  
  92.   if (!t)
  93.     t = s + strlen(s);
  94.   if (f_cpp_cmts) {
  95.     for (u = s; u < t - 1; u++)
  96.       if (*u == '/' && (u[1] == '*' || u[1] == '/'))
  97.     return 1;
  98.   } else {
  99.     for (u = s; u < t - 1; u++)
  100.       if (*u == '/' && u[1] == '*')
  101.     return 1;
  102.   }
  103.   return 0;
  104. }
  105.  
  106. /*
  107.    copy_comment() -- place a malloc()'ed copy of the comment beginning at |s|
  108.    into the global pointer |the_comment|.  Return a pointer to the first
  109.    character after the comment.
  110. */
  111. static char *copy_comment(s)
  112.   register char *s;
  113. {
  114.   register char *in_com, *t;
  115.   register int n;
  116.   register unsigned long in_comment;
  117.  
  118.   in_comment = this_line;
  119.   in_com = the_comment = mallok(len_comment = LINEBUF);
  120.   if (s[1] == '/') {
  121.     free(the_comment);
  122.     the_comment = strdup(s);
  123.     if (w_nest_cmts && nest_check(s + 2, (char *)0))
  124.       warning(SC_nested, in_comment);
  125.     return s + strlen(s);
  126.   }
  127.   for (;;) {
  128.     t = find_end_comment(s);
  129.     n = (!t ? strlen(s) + 2 : (int)(t - s) + 1);
  130.     in_com = grow(&the_comment, &len_comment, in_com, n);
  131.     (void)strncpy(in_com, s, n);
  132.     in_com += n;
  133.     if (!t)
  134.       *in_com++ = '\n';
  135.     *in_com = '\0';
  136.     if (w_nest_cmts && nest_check(s, t))
  137.       warning(SC_nested, in_comment);
  138.     if (t)
  139.       break;
  140.     s = getline();
  141.     if (!s) {
  142.       error(SC_unterm, in_comment);
  143.       in_com = grow(&the_comment, &len_comment, in_com, 3);
  144.       *in_com++ = '*';
  145.       *in_com++ = '/';
  146.       *in_com = '\0';
  147.       t = NULL;
  148.       break;
  149.     }
  150.   }
  151.   return t;
  152. }
  153.  
  154. /*
  155.    suck_comment() -- Skip over the comment beginning at |s|.  Return a
  156.    pointer to the first character after the comment.
  157. */
  158. static char *suck_comment(s)
  159.   register char *s;
  160. {
  161.   register char *t;
  162.   register unsigned long in_comment;
  163.  
  164.   if (keep_comments)
  165.     return copy_comment(s);
  166.   in_comment = this_line;
  167.   /* C++ comments end at the end of the line */
  168.   if (s[1] == '/') {
  169.     if (w_nest_cmts && nest_check(s + 2, (char *)0))
  170.       warning(SC_nested, in_comment);
  171.     return s + strlen(s);
  172.   }
  173.   for (;;) {
  174.     t = find_end_comment(s);
  175.     if (w_nest_cmts && nest_check(s + 2 * (this_line == in_comment), t))
  176.       warning(SC_nested, in_comment);
  177.     if (t) {
  178.       return t;
  179.     }
  180.     s = getline();
  181.     if (!s) {
  182.       error(SC_unterm, in_comment);
  183.       return NULL;
  184.     }
  185.   }
  186. }
  187.  
  188. /*
  189.    suck_ws() -- skip over whitespace characters after |s|, placing them
  190.    into the whitespace field of |T|.  Return a pointer to the first
  191.    non-whitespace character after |s|.
  192. */
  193. char *suck_ws(s, T)
  194.   register char *s;
  195.   TokenP T;
  196. {
  197.   register char *t, *u;
  198.   register int n;
  199.  
  200.   if (!spc_buf)
  201.     spc_buf = mallok(sz_spc_buf = SPC_GRAN);
  202.   u = spc_buf;
  203.   for (;;) {
  204.     t = s;
  205.     while (isspace(*s))
  206.       s++;
  207.     n = (int)(s - t);
  208.     u = grow(&spc_buf, &sz_spc_buf, u, n + 2);
  209.     (void)strncpy(u, t, n);
  210.     u += n;
  211.     *u = '\0';
  212.     if (!(*s == '/' && (s[1] == '*' || (f_cpp_cmts && s[1] == '/'))))
  213.       break;
  214.     s = suck_comment(s);
  215.     if (!keep_comments)
  216.       *u++ = ' ';
  217.     else {
  218.       n = strlen(the_comment);
  219.       u = grow(&spc_buf, &sz_spc_buf, u, n + 1);
  220.       (void)strcpy(u, the_comment);
  221.       free(the_comment);
  222.       u += n;
  223.     }
  224.     if (!s)
  225.       break;
  226.   }
  227.   *u = '\0';
  228.   set_ws(T, spc_buf);
  229.   return s;
  230. }
  231.  
  232. /* free_cmt_buf() -- free the mallok()'ed buffer used by suck_ws() */
  233. void free_cmt_buf()
  234. {
  235.   if (spc_buf)
  236.     free(spc_buf);
  237. }
  238.